fix(integrity): dedupe resolved packageIds at the source (#506)#509
Merged
fix(integrity): dedupe resolved packageIds at the source (#506)#509
Conversation
When multiple mops.toml dependency aliases (e.g. `base`, `base@0`, `base@0.16`) pin to the same `name@version`, `getResolvedMopsPackageIds` returned a list with duplicates, while `mops.lock`'s `hashes` map is naturally keyed by packageId. The integrity count check then failed with "Mismatched number of resolved packages" on otherwise-valid projects. Dedupe inside `getResolvedMopsPackageIds` so callers (registry queries and lockfile checks) see one entry per packageId. This also avoids sending duplicate ids to `getFileHashesByPackageIds` on the canister. Add a regression test fixture pinning `core` and `core@1` to the same version; without the fix `mops install` exits 1 with the mismatch error. Fixes #506. Made-with: Cursor
Made-with: Cursor
3 tasks
Kamirus
added a commit
that referenced
this pull request
Apr 23, 2026
…515) Fixes #514. ## What changes for users `mops install --lock update` now reliably regenerates `mops.lock` even when the existing lockfile has a stale or corrupt per-file hash. Previously this case silently no-op'd and then exited 1 on the follow-up integrity check, so `--lock update` could not recover a broken lock — the only escape hatch was `rm mops.lock`. That hatch is no longer required. Default `mops install` (no flag) is unchanged; the fast-path shortcut still fires when the lockfile's `mopsTomlDepsHash` matches. ## Root cause `updateLockFile` short-circuits via `checkLockFileLight`, which only validates `mopsTomlDepsHash`. When mops.toml hasn't changed but the lockfile's per-file `hashes` block is corrupt, the shortcut fires → nothing is rewritten → the subsequent `checkLockFile(force)` finds the same corrupt hash and calls `process.exit(1)`. Users get "Integrity check failed" with no way out except manual deletion of `mops.lock`. ## Fix Thread the existing `force` boolean from `checkIntegrity` into `updateLockFile`. `force = !!lock` is already true exactly when the user explicitly passed `--lock update`, so: - `mops install` (no flag, outside CI) → `force = false`, keeps the fast-path - `mops install --lock update` → `force = true`, bypasses the light-check shortcut, always regenerates - `mops install --lock check` / `--lock ignore` → unchanged ## Test plan Added a regression test (`--lock update rewrites a lockfile with a corrupt file hash`) that: 1. Runs `mops install` to produce a valid lockfile. 2. Surgically replaces one per-file hash with a bogus value. 3. Runs `mops install --lock update`. 4. Asserts exit 0 and that the bogus hash is no longer in the lockfile. Verified reverting the fix (restoring `updateLockFile()` / `if (checkLockFileLight()) return`) makes the new Jest test fail with the expected "Integrity check failed" / "Mismatched hash" error. ## Related - #509 (merged as part of 2.12.2) fixed the alias-tuple count mismatch that was the common *source* of corrupt lockfiles in the wild. This PR makes `--lock update` able to heal locks that were already written in the corrupt state. --------- Co-authored-by: Kamil Listopad <listopadkamil@gmail.com> Co-authored-by: Kamil Listopad <kamil.listopad@caffeine.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #506. Alternative to #507.
What changes for users
mops install(and any flow that runs--lock check) no longer fails withMismatched number of resolved packages: N vs Mon projects whose resolved deps include multiple aliases (e.g.base,base@0,base@0.16) pinned to the samename@version. Previously the only workaround was--lock ignore.Root cause
getResolvedMopsPackageIdsreturned a list with duplicates:resolvePackages()keeps each alias as its own entry, thengetPackageIdcollapses the alias suffix viagetDepName, so two aliases pinning the samename@versionproduced the same id twice.mops.lock'shashesis keyed by packageId and naturally dedup'd, so the count comparison incheckLockFilemismatched.Why this approach over #507
#507 dedupes only at the count comparison. This PR dedupes inside
getResolvedMopsPackageIds, which (a) makes the function's contract match its name, and (b) stops sending duplicate ids to the canister'sgetFileHashesByPackageIds. Downstream membership checks (includes,in) were already dedupe-safe, so no other call site needed changes.Test plan
Added a regression fixture pinning
coreandcore@1to1.0.0plus a test assertingmops installexits clean and stderr doesn't contain the mismatch error. Verified that reverting the fix makes the Jest test fail with the expected error string.